Skip to content

refactor(docs): 统一 /docs、CommunityShare、Leetcode 三处索引为 <SectionIndex>(取代 #288 #290)#292

Merged
longsizhuo merged 3 commits intomainfrom
refactor/unified-section-index
Apr 16, 2026
Merged

refactor(docs): 统一 /docs、CommunityShare、Leetcode 三处索引为 <SectionIndex>(取代 #288 #290)#292
longsizhuo merged 3 commits intomainfrom
refactor/unified-section-index

Conversation

@longsizhuo
Copy link
Copy Markdown
Member

合并 #288 + #290 + Leetcode/index.mdx 三处各自实现的"列目录子节点"逻辑为一个组件。

背景

三处独立实现:

位置 形式 做法
`app/docs/page.tsx`(PR #290 draft) server component 读 `pageTree.children` → Cards
`app/components/CommunityShareIndex.tsx`(PR #288 draft) server component 读 `getPages()` 过滤 path → 分组列表 + 折叠
`app/docs/CommunityShare/Leetcode/index.mdx` 内联 MDX `source.getPages().filter().map()`

drift 风险具体:排序规则 / 英文版过滤 / 没 index 时的 fallback URL 三份逻辑各走各的。Copilot 在 #288 里还指出了一个真 bug:没 `index.mdx` 的子目录(`Language` / `Life` / `Personal-Study-Notes` / `RAG`)硬拼 `/docs/CommunityShare/

` 链接,点进去全部 404——和 PR #290 要修的 `/docs` 根路由 404 是同一个根因:Next `[...slug]` 不匹配空 slug,folder 没 index.mdx 就意味着 `/docs/X` 没任何 route。

方案

一个组件 `<SectionIndex root?>`:

  • 走 `source.pageTree`(不是 `getPages`),fumadocs 已经把 folder + 可选 index 的结构建好了,不用从扁平 page 列表反推
  • `root` 接 `"CommunityShare"` / `"CommunityShare/Leetcode"` 这种相对路径;不传就从 pageTree 根开始
  • URL 永不硬拼:folder 有 index → `folder.index.url`;没 index → 递归找子树第一个 page 的 url 兜底(直接修掉 CR 那个 404 bug)
  • 英文翻译版(URL 末段 `.en`)过滤不进列表;语言切换仍由 `[...slug]` 的 cookie fallback 负责
  • 统一 fumadocs `` / `` 视觉

接入的三处

```tsx
// /docs landing

// CommunityShare 分区首页

// Leetcode 分区首页

```

本地验证

```
/docs → 200 (5 张卡片)
/docs/CommunityShare → 200 (8 张卡片)
/docs/CommunityShare/Leetcode → 200 (49 张卡片,0 个 .en 泄漏)
```

重点验证 CR 提到的 4 个没 index.mdx 的子目录链接——现在全部落到子目录里第一篇 page,200 可达:

```
/docs/CommunityShare/Language/pte-intro → 200
/docs/CommunityShare/Life/unsw-student-benefit → 200
/docs/CommunityShare/Personal-Study-Notes/Reinforcement-Learning/ppo → 200
/docs/CommunityShare/RAG/context_engineering_intro → 200
```

取代关系

Test plan

  • `pnpm tsc --noEmit` 对新/改文件无报错
  • 本地 dev server 三个 URL 都 200
  • CommunityShare 索引 8 张卡片全部点击可达(包括原先会 404 的 4 个)
  • Leetcode 索引 49 张卡片、无英文翻译泄漏
  • 合并部署后生产 `/docs`、`/docs/CommunityShare`、`/docs/CommunityShare/Leetcode` 目视过一遍

合并 #288 + #290 + app/docs/CommunityShare/Leetcode/index.mdx 里原先三份
各自实现的"列目录子节点"逻辑,改成一个 server component。

## 为什么要合并

原本三处各自实现:
- /docs 根路由(PR #290 draft)—— 读 pageTree.children
- CommunityShare/index.mdx(PR #288 draft)—— 读 getPages() 过滤 path
- CommunityShare/Leetcode/index.mdx —— 内联 MDX 里 source.getPages().filter().map()

drift 问题:排序、英文过滤、fallback URL 三份逻辑各走各的;更严重的是
PR #288 里对"没 index.mdx 的子目录"硬拼 /docs/CommunityShare/<dir> 会 404
(Copilot CR 指出),和 PR #290 修 /docs 404 是同一个根因:Next [...slug]
不匹配空 slug,folder 没 index 就意味着 /docs/X 没 route。

## <SectionIndex root?>

- 走 source.pageTree(不是 getPages),fumadocs 已经把 folder+index
  关系建好了,不用自己从扁平 page 列表反推
- root 接 "CommunityShare" / "CommunityShare/Leetcode" 这种相对路径,
  不传就是从 pageTree 根开始(给 /docs landing 用)
- URL 永不硬拼:folder 有 index 走 index.url;没 index 递归找子树第一个
  page 的 url 作为 fallback(直接修掉 CR 那个 404 bug)
- 英文翻译版(URL 末段 .en)过滤不进列表;语言切换仍由 [...slug] 的 cookie
  fallback 负责
- 统一 fumadocs <Cards>/<Card> 视觉

## 本地验证

- /docs → 5 张卡片,全部 200
- /docs/CommunityShare → 8 张卡片,全部 200(包括原先会 404 的 Language/
  Life/Personal-Study-Notes/RAG 四个没 index 的分类,现在点进去是子目录里
  第一篇 page,不再死链)
- /docs/CommunityShare/Leetcode → 49 张卡片,0 个 .en 泄漏

## 取代关系

- 关闭 PR #288(CommunityShareIndex 专用实现,有 404 bug)
- 关闭 PR #290(/docs landing 单独实现)
- 本 PR 一并覆盖,继续承担解决 #110 的责任

Co-authored-by: LynPtl <194795025+LynPtl@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 16, 2026 19:18
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
involutionhell-github-io Ready Ready Preview, Comment Apr 16, 2026 8:44pm
website-preview Ready Ready Preview, Comment Apr 16, 2026 8:44pm

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

本 PR 将 /docs landing、CommunityShare 分区首页、CommunityShare/Leetcode 分区首页三处“列出子节点目录/页面”的索引逻辑,统一收敛为一个可复用的 Server Component:<SectionIndex root?>,避免三份实现产生 drift,并修复“无 index 的目录被硬拼 URL 导致 404”的同源问题。

Changes:

  • 新增通用索引组件 SectionIndex:基于 source.pageTree 生成 Cards 列表,并为无 index 的 folder 递归兜底到子树第一个可用 page URL
  • 新增 /docs 根路由 app/docs/page.tsx,使用 <SectionIndex /> 生成 landing(解决 /docs 404)
  • CommunityShareLeetcode 的 index.mdx 改为直接使用 <SectionIndex root="...">,移除内联/硬编码索引实现

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
app/docs/page.tsx 新增 /docs landing 页,读取 locale cookie 并渲染 <SectionIndex />
app/docs/CommunityShare/index.mdx <SectionIndex root="CommunityShare" /> 替换手写分类列表
app/docs/CommunityShare/Leetcode/index.mdx <SectionIndex root="CommunityShare/Leetcode" /> 替换内联 getPages().filter().map()
app/components/docs/SectionIndex.tsx 新增通用索引组件:从 pageTree 构建 Cards、处理 folder 无 index 的 fallback

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/components/docs/SectionIndex.tsx Outdated
Comment on lines +78 to +84
/** 判定页面是英文翻译版(不应出现在索引里) */
function isEnglishVariant(page: PageNode): boolean {
// PageTree 节点 name 可能是 string | ReactNode;英文变体的 frontmatter.lang === "en"
// 但 pageTree 级别看不到 frontmatter,只能靠 URL 末段后缀兜底
const urlSlug = page.url.split("/").pop() ?? "";
return urlSlug.endsWith(".en");
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isEnglishVariant 只过滤了 URL 末段以 .en 结尾的翻译页,但当前 docs 的语言变体规则在 [...slug]/page.tsx 里是 ${slug}.${locale}(支持 zh / en)。在 Leetcode 目录里也能看到不少 *.zh.md 文件名;如果这些页被纳入 pageTree,会导致 .zh 翻译页仍然出现在索引卡片中、产生重复/非 canonical 链接。建议把这里的过滤改成“过滤所有语言后缀页”(例如同时排除 .en.zh),并相应调整函数命名/注释。

Copilot uses AI. Check for mistakes.
Comment thread app/components/docs/SectionIndex.tsx Outdated
}
// folder
const folder = node as FolderNode;
const idxUrl = folder.index?.url;
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里对 folder 的链接优先直接使用 folder.index?.url,但没有对 folder.index 做语言后缀过滤;如果某个目录只有 index.en/ index.zh 这类变体页(或 index 被解析为带后缀的 URL),就会把翻译页作为卡片链接暴露出来。建议在选择 idxUrl 时也复用同一套“过滤语言后缀页”的判断(不合规时退回 findFirstPageUrl)。

Suggested change
const idxUrl = folder.index?.url;
const idxUrl =
folder.index && !isEnglishVariant(folder.index) ? folder.index.url : null;

Copilot uses AI. Check for mistakes.
Comment thread app/components/docs/SectionIndex.tsx Outdated

/**
* fumadocs 的 FolderNode.name 是 ReactNode(可能是字符串,也可能是 JSX),
* 单靠 name 匹配不稳定。这里优先用 index 页的 slug 倒数第二段反推目录名,
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释里写“用 index 页的 slug 倒数第二段反推目录名”,但下面实现实际取的是 folder.index.url最后一段parts[parts.length - 1])。建议修正注释描述,避免后续维护者按注释误解实现。

Suggested change
* 单靠 name 匹配不稳定。这里优先用 index 页的 slug 倒数第二段反推目录名
* 单靠 name 匹配不稳定。这里优先用 index 页的 slug 最后一段反推目录名

Copilot uses AI. Check for mistakes.
Comment thread app/docs/page.tsx
Comment on lines +15 to +18
async function getLocaleFromCookie(): Promise<"zh" | "en"> {
const cookieStore = await cookies();
return cookieStore.get("locale")?.value === "en" ? "en" : "zh";
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getLocaleFromCookie 的 cookie 读取逻辑在 app/layout.tsxi18n/request.tsapp/docs/[...slug]/page.tsx 等处已有重复实现;这里又新增一份,后续如果 locale cookie 规则变化会更容易 drift。建议抽一个共享的 server-side helper(例如 lib/locale.ts),并在这些入口统一复用。

Copilot uses AI. Check for mistakes.
Copilot 在 #292 提了 3 条要修的:

1) isEnglishVariant 只过滤 .en,没管 .zh —— 站点实际有 .zh.md(原文是 en 时的中文翻译),
   重复链接会在索引里暴露。改成 isHideableLocaleVariant(url, canonicals):只有对应
   canonical 存在时才隐藏,孤儿(只有 .en 或 .zh 单一形态的文档,共 35 + 7 篇)保留。

2) folder.index 如果本身是翻译版(理论上会有 index.en.mdx / index.zh.mdx),不能直接
   当卡片 href,会暴露非 canonical URL。nodeToCard 里给 idxUrl 加同样的过滤,不合规时
   退回 findFirstPageUrl。

3) folderSegmentName 注释写的"倒数第二段"但代码取的是最后一段,改掉注释。

另外按用户反馈清掉注释里的 markdown(**bold**、反引号等),代码注释又不会被渲染。
@longsizhuo longsizhuo merged commit 479b566 into main Apr 16, 2026
6 of 8 checks passed
@longsizhuo longsizhuo deleted the refactor/unified-section-index branch April 16, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants